///////////////////////////////////////////////////////////////////////////////////////////////////
/// \file formic/fqmc/energy.h
///
/// \brief   header file for the monte carlo energy function
///
///////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef FORMIC_FQMC_ENERGY_HEADER
#define FORMIC_FQMC_ENERGY_HEADER

#include<formic/random/random.h>

#include<boost/shared_ptr.hpp>

namespace formic {

  class InputBase;
  class Configuration;
  template<class S> class CoeffObj;

  namespace fqmc {

    template<class S> class Sampler;

    template<class S> double energy(const formic::InputBase & userinp,
                                    const boost::shared_ptr<formic::CoeffObj<S> > & co,
                                    double & sdev,
                                    double & serr,
                                    const bool print = true);

    template<class S> double energy(const formic::InputBase & userinp,
                                    boost::shared_ptr<formic::fqmc::Sampler<S> > & sampler,
                                    const boost::shared_ptr<formic::CoeffObj<S> > & co,
                                    double & sdev,
                                    double & serr,
                                    const bool print = true);

    template<class S> double energy(const formic::InputBase & userinp,
                                    const int burn_len,
                                    const int samp_len,
                                    const formic::Configuration & init_config,
                                    const formic::LaggedFibonacci<> & rng,
                                    const boost::shared_ptr<formic::CoeffObj<S> > & gf,
                                    const boost::shared_ptr<formic::CoeffObj<S> > & vf,
                                    double & sdev,
                                    double & serr,
                                    const bool print = true);

    template<class S> inline double energy(const formic::InputBase & userinp,
                                           const boost::shared_ptr<formic::CoeffObj<S> > & co) {
      double sdev = 0.0;
      double serr = 0.0;
      return formic::fqmc::energy(userinp, co, sdev, serr);
    }

    template<class S> inline double energy(const formic::InputBase & userinp,
                                           const int burn_len,
                                           const int samp_len,
                                           const formic::Configuration & init_config,
                                           const formic::LaggedFibonacci<> & rng,
                                           const boost::shared_ptr<formic::CoeffObj<S> > & gf,
                                           const boost::shared_ptr<formic::CoeffObj<S> > & vf) {
      double sdev = 0.0;
      double serr = 0.0;
      return formic::fqmc::energy(userinp, burn_len, samp_len, init_config, rng, gf, vf, sdev, serr);
    }

    template<class S> inline double energy(const formic::InputBase & userinp,
                                           boost::shared_ptr<formic::fqmc::Sampler<S> > & sampler,
                                           const boost::shared_ptr<formic::CoeffObj<S> > & co) {
      double sdev = 0.0;
      double serr = 0.0;
      return formic::fqmc::energy(userinp, sampler, co, sdev, serr);
    }

  }

}

#endif
